package com.iqiyi.pps.epg.web.timer;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.iqiyi.kiwi.utils.HttpClientConnection;
import com.iqiyi.pps.epg.core.model.channel.ChannelBase;
import com.iqiyi.pps.epg.core.model.channel.ChannelConfig;
import com.iqiyi.pps.epg.core.model.channel.ChannelLog;
import com.iqiyi.pps.epg.core.model.control.PlatformControl;
import com.iqiyi.pps.epg.core.model.control.ProgramPlatformControl;
import com.iqiyi.pps.epg.core.model.program.*;
import com.iqiyi.pps.epg.core.model.rtmp.RtmpServer;
import com.iqiyi.pps.epg.core.model.stream.LiveChannelStream;
import com.iqiyi.pps.epg.core.model.stream.LiveStream;
import com.iqiyi.pps.epg.core.service.broadcast.BroadcastControlService;
import com.iqiyi.pps.epg.core.service.channel.ChannelService;
import com.iqiyi.pps.epg.core.service.notifymail.NotifyMailService;
import com.iqiyi.pps.epg.core.service.program.ProgramService;
import com.iqiyi.pps.epg.core.service.rtmp.RtmpService;
import com.iqiyi.pps.epg.core.service.stream.LiveChannelStreamService;
import com.iqiyi.pps.epg.core.service.stream.LiveStreamService;
import com.iqiyi.pps.epg.core.utils.*;
import com.iqiyi.pps.epg.core.utils.mail.MailConstant;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

/**
 * Created by karkarrotxu on 2015/7/24.
 */
public class CheckListTrigger {
    private static Logger logger = LoggerFactory.getLogger(CheckListTrigger.class);
    private static Map<Long, ProgramCheckData> checkMap = new HashMap<Long, ProgramCheckData>();
    private static String PROGRAM_CHECK_TITLE = "临时直播检查";
    private static String CHANNEL_TAG_URL = "http://xinqi.if.iqiyi.com/basic/categories.json";

    private static String VRS_VIP_URL = "http://port.qiyi.com/live/vip/ts";// disable in dev mode  , mail to limingrui@qiyi.com
    private static String FLV_BASE_URL = "http://www.iqiyi.com/common/flashplayer/20141218/LivePlayer_3_0_3_4.swf?vid=%s&source=live.lego.iqiyi.com&cid=qc_100001_300089";
    private static String SERVER_STAT_URL = "http://%s:%s/stat";
    private static String PREVIEW_URL = "http://www.cutv.com/demo/live_test.swf?url=rtmp://%s/live/%s";
    private static String QUERY_SPAN_URL = "http://cutteradmin.qiyi.domain:7777/";
    private static String REMIND_TIME_1 = "提前24小时阶段";
    private static String REMIND_TIME_2 = "提前2小时阶段";

    private static String BEFORE_TIME_1 = "提前30分钟阶段";
    private static String BEFORE_TIME_2 = "提前5分钟阶段";
    private static String AFTER_TIME_1 = "节目开始10分钟阶段";
    private static String FORCE_TIME = "紧急执行阶段";
    private static String LEVEL_101 = "A类一级";

    private static long restNum = 0;
    @Autowired
    private ChannelService channelService;
    @Autowired
    private ProgramService programService;

    @Autowired
    private NotifyMailService notifyMailService;

    @Autowired
    private LiveChannelStreamService liveChannelStreamService;
    @Autowired
    private BroadcastControlService broadcastControlService;
    @Autowired
    private LiveStreamService liveStreamService;
    @Autowired
    private RtmpService rtmpService;

    private Map<Long, String> categoriesMap = new HashMap<Long, String>();

    public static final long BUFF_TIME = 300000L;

    private static Map<String, String> VRS_CODE_RESULT = new HashMap<String, String>() {{
        put("A00000", "请求成功");
        put("A00001", "请求参数无效");
        put("A00003", "内部请求异常");
        put("A00004", "请求无数据");
        put("A00005", "请求数据为不可用状态");
        put("A00110", "平台受限");
        put("A00111", "用户所在地域受限");
    }};
    private long loopMin = 0;
    private long loopMax = 0;

    public void initPlayPlatformInUse() {
        List<ChannelConfig> configs = channelService.getConfig("PlayPlatform");
        MailContentUtil.CLIENT_INUSE_NUMBER = configs.size();
        logger.info("CLIENT_INUSE_NUMBER:" + MailContentUtil.CLIENT_INUSE_NUMBER);

    }

    public void task() {
        restNum++;
        if (restNum > 1) {
            return;
        }
        categoriesMap.clear();
        initPlayPlatformInUse();
        while (restNum > 0) {
            try {
                long checkStartTime = System.currentTimeMillis();
                loopMin = checkStartTime - ProgramCheckData.CHECK_AFTER_TIME;
                loopMax = checkStartTime + DateTimeUtil.DAY_TIME + BUFF_TIME;
                List<ProgramData> list = programService.checkListQuery(loopMin, loopMax, true);
                if (list.size() > 0) {
                    ProgramCheckData checkData = null;
                    for (ProgramData p : list) {
                        if (p.getDeleteFlag() == 1) {
                            if (checkMap.containsKey(p.getId())) {
                                checkMap.remove(p.getId());
                                logger.info("[remove program][pid={}][qipuId={}]", p.getId(), p.getQipuId());
                            }
                            continue;
                        }
                        if (!checkMap.containsKey(p.getId())) {
                            checkData = new ProgramCheckData();
                            checkData.setId(p.getId());
                            checkData.setFatherId(p.getFatherId());
                            checkData.initByStartTime(p.getStartPlayTime().getTime());
                            checkMap.put(checkData.getId(), checkData);
                        } else {
                            checkData = checkMap.get(p.getId());
                            if (checkData.getStartTime() != p.getStartPlayTime().getTime()) {
                                checkData.initByStartTime(p.getStartPlayTime().getTime());
                            }
                        }
                    }
                }
                List<ProgramCheckData> checkList = new ArrayList<ProgramCheckData>(checkMap.values());
                List<Long> removeList = new ArrayList<Long>();
                for (ProgramCheckData temp : checkList) {
                    ProgramCheckData.STATUS status = temp.getCheckStatus(checkStartTime);
                    switch (status) {
                        case PHASE_OVER_CHECK:
                            if (doSendCheckListMail(temp, AFTER_TIME_1)) {
                                temp.setLastExcuteTime(checkStartTime);
                                removeList.add(temp.getId());
                            }
                            break;
                        case PHASE_CHECK_SECOND:
                            if (doSendCheckListMail(temp, BEFORE_TIME_2)) {
                                temp.setLastExcuteTime(checkStartTime);
                            }
                            break;
                        case PHASE_CHECK_FIRST:
                            if (doSendCheckListMail(temp, BEFORE_TIME_1)) {
                                temp.setLastExcuteTime(checkStartTime);
                            }
                            break;
                        case PHASE_REMIND_TIME2:
                            if (doSendRemindMail(temp, REMIND_TIME_2)) {
                                temp.setLastExcuteTime(checkStartTime);
                            }
                            break;
                        case PHASE_REMIND_TIME1:
                            if (doSendRemindMail(temp, REMIND_TIME_1)) {
                                temp.setLastExcuteTime(checkStartTime);
                            }
                            break;
                        case IN_WAIT:
                            break;
                    }
                }
                if (removeList.size() > 0) {
                    logger.info("[CheckListTrigger][task]remove " + removeList.toString());
                    for (Long removeId : removeList) {
                        checkMap.remove(removeId);
                    }
                }
                doforceCheck();
            } catch (Exception e) {
                logger.error("[CheckListTrigger][task]", e);
            } finally {
                restNum--;
            }
        }
    }

    private void doforceCheck() {
        List<ProgramCheckData> checkDataList = programService.findForceCheck();
        for (ProgramCheckData temp : checkDataList) {
            if (doSendCheckListMail(temp, FORCE_TIME)) {
                programService.doEndForceCheck(temp.getId());
            }
        }
    }

    public boolean doSendRemindMail(ProgramCheckData pcd, String titlePlus) {
        boolean flag = false;
        try {
            ChannelBase channelBase = channelService.getChannelBase(pcd.getFatherId());
            ProgramData programData = programService.findProgramDataById(pcd.getId());
            if (programData == null) {
                return false;
            }
            Map<String, String> map = new HashMap<String, String>();
            map.put(MailConstant.C_ID, channelBase.getId() + "");
            map.put(MailConstant.P_NAME, programData.getPname());
            map.put(MailConstant.P_QIPU_ID, programData.getQipuId() + "");
            map.put("programStartTime", DateTimeUtil.transLongFormat(programData.getStartPlayTime().getTime()));
            map.put(MailConstant.C_NAME, channelBase.getName());
            map.put(MailConstant.C_QIPU_ID, channelBase.getQipuId() + "");
            map.put(MailConstant.TITLE_PLUS, titlePlus);
            notifyMailService.addMailAsyncTask(MailConstant.TOS_TYPE_LS_REMIND, MailContentUtil.ContentType.LS_START_REMIND.getTypeIndex(), map);
            flag = true;
        } catch (Exception e) {
            logger.error("[exception={}]", e);
        }
        return flag;
    }

    public boolean doSendCheckListMail(ProgramCheckData pcd, String titlePlus) {
        ChannelBase channelBase = channelService.getChannelBase(pcd.getFatherId());
        ProgramData programData = programService.findProgramDataById(pcd.getId());
        boolean isForce = FORCE_TIME.equals(titlePlus);
        if (programData == null) {
            logger.warn("[doSendCheckListMail][pid:{}] is null ", pcd.getId());
            checkMap.remove(pcd.getId());
            return false;
        }
        if (!isForce) {
            if (programData.getStartPlayTime().getTime() < loopMin || programData.getStartPlayTime().getTime() > loopMax) {
                logger.warn("[doSendCheckListMail][pid:{}] is  {} out of time range [{},{}]", pcd.getId(), programData.getStartPlayTime().getTime(), loopMin, loopMax);
                checkMap.remove(pcd.getId());
                return false;
            }
        }
        JSONObject programEntity = null;
        JSONObject channelEntity = null;
        if (programData.getQipuId() > 0) {
            programEntity = ApiQipuUtil.rpcReadQipuEntity(programData.getQipuId());
        }
        if (channelBase.getQipuId() > 0) {
            channelEntity = ApiQipuUtil.rpcReadQipuEntity(channelBase.getQipuId());
        }

        ProgramCheckListData qipuData = fetchQipuData(channelEntity, programEntity);
        if (qipuData == null) {
            logger.info("[doSendCheckListMail] fail get channelId: " + pcd.getFatherId() + " programId:" + pcd.getId());
            return false;
        }
        ProgramCheckListData localData = fetchLocalData(channelBase, programData);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("qipuDB", qipuData);
        map.put("localData", localData);
        if (qipuData.isHasError() || localData.isHasError()) {
            notifyDecodeError(qipuData, localData);
        }
        if (FORCE_TIME.equalsIgnoreCase(titlePlus) || AFTER_TIME_1.equalsIgnoreCase(titlePlus) || (BEFORE_TIME_2.equalsIgnoreCase(titlePlus) && LEVEL_101.equals(localData.getEpisodeGrade()))) {
            checkSendMsg(qipuData, localData);
        }
        String content = MailContentUtil.getContent(MailContentUtil.ContentType.CHECK_LIST, map);
        boolean flag = SendMailUtils.sendMail(PROGRAM_CHECK_TITLE + titlePlus, getTagerts(), content);
        return flag;
    }

    public String[] getTagerts() {
        return notifyMailService.getTos(0, 0, MailConstant.TOS_TYPE_LS_CHECK_LIST);
    }

    public ProgramCheckListData fetchLocalData(ChannelBase channelBase, ProgramData programData) {
        ProgramCheckListData data = new ProgramCheckListData();
        try {
            //relation 替换
            data.setChannelName(channelBase.getName());
            data.setChannelAllowPopUps(channelBase.getAllowPopups() == 1);
            data.setChannelQitanId(channelBase.getQitanId());
            data.setChannelQiTanShow(channelBase.getShouldDisplay() == 1);
            data.setSubjectUrl(channelBase.getSubjectUrl());
            data.setDefaultLogoUrl(channelBase.getDefaultLogoUrl());
            data.setChannelQipuId(channelBase.getQipuId());
            data.setProgramQipuId(programData.getQipuId());
            data.setChannelOldQipuId(channelBase.getOldQipuId());
            data.setEnable(channelBase.getIsEnable() == 1);
            //relation program
            data.setProgramName(programData.getPname());
            data.setEpisodeGrade(channelService.getConfigData("EpisodeGradeType", programData.getEpisodeGrade()).getDescr());
            data.setProgramBoss(programData.getBossStatus());
            data.setProgramDefaultLogoUrl(programData.getDefaultLogoUrl());
            data.setStartTime(DateTimeUtil.transLongFormat(programData.getStartPlayTime().getTime()));
            data.setEndTime(DateTimeUtil.transLongFormat(programData.getStopPlayTime().getTime()));
            data.setPageUrl(programData.getPageUrl());
            data.setProgramAllowPopUps(programData.getAllowPopups() == 1);
            doLocalDataTagFill(data, programData);
            doLiveChannelStream(data, channelBase.getId());
            doLocalDataOnlineStatus(data, channelBase.getId(), programData.getId());

            //2016-04-20新增内容
            data.setChatEnable(programData.getChatEnable() > 0);
            data.setChatDisplay(programData.getChatDisplay() > 0);
            data.setChatRoomId(programData.getChatRoomId());
            data.setProgramQitanId(programData.getQitanId());
            data.setProgramQiTanShow(programData.getAllowComment() > 0);
            data.setDaojuId(programData.getDaojuId());
            data.setDaojuEnable(programData.getDaojuEnable() > 0);
        } catch (Exception e) {
            logger.error("[CheckListTrigger][fetchLocalData][fetchLocalData]", e);
            data.setHasError(true);
            data.setCheckErrorMsg("[deocde local_base error]");
        }
        return data;
    }

    public void queryCategories(long fatherId) {
        Map<String, Object> params = null;
        if (fatherId > 0) {
            params = new HashMap<String, Object>();
            params.put("father_id", fatherId + "");
        }

        String retValue = ApiHttpRequestUtil.originalGet(CHANNEL_TAG_URL, params, null);
        if (retValue != null) {
            List<TagJSON> list = JSON.parseArray(retValue, TagJSON.class);
            for (TagJSON tag : list) {
                categoriesMap.put(tag.getId(), tag.getName());
            }
        }
    }

    //programTag 替换
    public void doLocalDataTagFill(ProgramCheckListData data, ProgramData programData) {
        StringBuilder stringBuilder = new StringBuilder(256);
        String tagDetail = programData.getProgramTag();
        if (StringUtils.isNotBlank(tagDetail)) {
            String[] tagArr = tagDetail.split(",");
            String[] tempArr = null;
            for (String single : tagArr) {
                tempArr = single.split("_");
                if (tempArr.length > 0) {
                    if (!categoriesMap.containsKey(Long.valueOf(tempArr[0]))) {
                        queryCategories(0);
                    }
                    stringBuilder.append(categoriesMap.get(Long.valueOf(tempArr[0])));
                }
                if (tempArr.length > 1 && Long.valueOf(tempArr[1]).intValue() > 0) {
                    if (!categoriesMap.containsKey(Long.valueOf(tempArr[1]))) {
                        queryCategories(Long.valueOf(tempArr[0]));
                    }
                    stringBuilder.append("_" + categoriesMap.get(Long.valueOf(tempArr[1])));
                }
                stringBuilder.append(",");
            }
        }
        if (stringBuilder.length() > 0) {
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
        }
        data.setProgramTag(stringBuilder.toString());
        //channelTag end
    }


    //  流数据 编码状态
    //  流数据 8080端口访问
    public void doLiveChannelStream(ProgramCheckListData data, long channelId) {
        List<LiveChannelStream> list = liveChannelStreamService.getByIsEnable(channelId, true);
        if (list.size() > 0) {
            String serverIp = null;
            Map<String, Boolean> statMap = new HashMap<String, Boolean>();
            List<LiveStream> liveStreamList = liveStreamService.get(channelId);
            Map<String, LinkData> map = data.getStreamMap();
            ChannelStreamData channelStreamData = null;
            LinkData linkData = null;
            List<ChannelStreamData> csdList = new ArrayList<ChannelStreamData>();

            List<RtmpServer> serverList = rtmpService.getServerList();
            Map<String, Integer> serverPortMap = transferServerList(serverList);
            Map<String, String> serverListMap = makeServerListMap(serverList);
            List<Criterion> expressionList = null;
            //select *  from channel_log where father_id = 100939 and (type = 234 or type = 235) and descr like '%lb_songzhongji_high%' order by add_time desc limit 1
            for (LiveChannelStream liveChannelStream : list) {
                expressionList = new ArrayList<>();
                expressionList.add(Restrictions.eq("fatherId", liveChannelStream.getFatherId()));
                expressionList.add(Restrictions.or(Restrictions.eq("type", Constants.LogType.ENCODE_START.getIndex()), Restrictions.eq("type", Constants.LogType.ENCODE_STOP.getIndex())));
                expressionList.add(Restrictions.like("descr", liveChannelStream.getStreamName(), MatchMode.ANYWHERE));

                serverIp = liveChannelStream.getStreamIp();
                if (StringUtils.isBlank(serverIp)) {
                    if (liveChannelStream.getEncodeType() == 0) {
                        logger.error("cid:" + channelId + "|sid:" + liveChannelStream.getId() + "|sn:" + liveChannelStream.getStreamName() + "| getStreamIp is empty");
                    }
                    continue;
                }
                // get the private ip for the serverIP
                serverIp = null == serverListMap.get(serverIp) ? serverIp : serverListMap.get(serverIp);

                channelStreamData = new ChannelStreamData();
                channelStreamData.setStreamAspectRatio(liveChannelStream.getAspectRatio());
                channelStreamData.setStreamType(liveChannelStream.getStreamType());
                channelStreamData.setStreamName(liveChannelStream.getStreamName());
                channelStreamData.setHasDolby(StringUtils.isNotEmpty(liveChannelStream.getDolbyStreamName()));
                /* channelLog addtime start */
                List<ChannelLog> logList = channelService.findChannelLogList(expressionList, 2, Order.desc("addTime"));
                if (logList.size() > 0) {
                    ChannelLog channelLog = logList.get(0);
                    channelStreamData.setLogType(channelLog.getType());
                    channelStreamData.setLogTime(DateTimeUtil.transLongFormat(channelLog.getAddTime().getTime()));
                }
                /*channelLog addtime end  */

                csdList.add(channelStreamData);
                channelStreamData.setEncodeRed(liveChannelStream.getStatus() == 0);
                if (!statMap.containsKey(serverIp)) {
                    boolean canVisit = canVisitServer(serverIp, serverPortMap.get(serverIp));
                    statMap.put(serverIp, canVisit);
                }
                channelStreamData.setVisitRed(!statMap.get(serverIp));
                linkData = channelStreamData.getPreView();
                linkData.setShowUrl("流预览");
                linkData.setLink(String.format(PREVIEW_URL, serverIp, liveChannelStream.getStreamName()));
                linkData = channelStreamData.getServerStat();
                linkData.setShowUrl(serverIp + "服务器访问");
                linkData.setLink(String.format(SERVER_STAT_URL, serverIp, serverPortMap.get(serverIp)));
                if (StringUtils.isNotBlank(liveChannelStream.getDolbyStreamName())) {
                    linkData.setDolbyLink(true);
                    linkData.setDolbyUrl(liveChannelStream.getDolbyStreamUrl());
                    linkData.setDolbyName(liveChannelStream.getDolbyStreamName());
                }
                if (liveStreamList != null && liveStreamList.size() > 0) {
                    for (LiveStream stream : liveStreamList) {
                        if (stream.getStatus() == 1 && stream.getStreamName().equals(liveChannelStream.getStreamName())) {
                            linkData = new LinkData();
                            linkData.setStreamFormatType(stream.getFormatType());
                            linkData.setUniqueKey(liveChannelStream.getStreamType() + "_" + stream.getFormatType());
                            linkData.setShowUrl(stream.toQipuUrl());
                            if (linkData.isFLv()) {
                                linkData.setLink(flvLink(stream.getUrl()));
                            } else if (linkData.isTs()) {
                                linkData.setLinkFormat(false);
                            } else if (linkData.isDolby()) {
                                linkData.setLinkFormat(false);
                            }
                            map.put(linkData.getUniqueKey(), linkData);
                        }
                    }
                }
            }
            data.setChannelStreamDataList(csdList);
        }
    }


    private static String flvLink(String url) {
        return String.format(FLV_BASE_URL, url);
    }

    private static boolean canVisitServer(String serverIp, Integer port) {
        HttpClientConnection connection = null;
        String statUrl = String.format(SERVER_STAT_URL, serverIp, port);
        for (int i = 0; i < 3; i++) {
            connection = new HttpClientConnection(statUrl, HttpClientConnection.GET_METHOD);
            connection.setSoTimeout(5000);
            connection.connect();
            if (connection.getStatus() == 200) {
                return true;
            }
        }
        return false;
    }

    //各端上线情况
    public void doLocalDataOnlineStatus(ProgramCheckListData data, long channelId, long programId) {
        List<PlatformControl> list = broadcastControlService.getPlatformControls(channelId);
        List<ChannelConfig> channelConfigList = channelService.getConfig("PlayPlatform");
        Map<Integer, String> channelMap = new HashMap<Integer, String>();
        for (ChannelConfig config : channelConfigList) {
            channelMap.put(config.getKey(), config.getVal());
        }
        for (PlatformControl temp : list) {
            if (temp.getAvailableStatus() == 1) {
                data.addOnlinePlatform(channelMap.get(temp.getPlayPlatform()));
            }
        }
        List<ProgramPlatformControl> list_program = broadcastControlService.getProgramPlatformControls(programId);
        for (ProgramPlatformControl temp : list_program) {
            if (temp.getAvailableStatus() == 1) {
                data.addProgramOnlinePlatform(channelMap.get(temp.getPlayPlatform()));
            }
        }
    }

    public static ProgramCheckListData fetchQipuData(JSONObject channelEntity, JSONObject programEntity) {


        ProgramCheckListData data = new ProgramCheckListData();
        try {
            JSONObject liveChannelBase = channelEntity.getJSONObject("live_channel_base");
            data.setChannelName(liveChannelBase.getString("name"));
            data.setChannelAllowPopUps(liveChannelBase.containsKey("allow_popups") && liveChannelBase.getBoolean("allow_popups"));
            data.setChannelQipuId(channelEntity.getLong("id"));

            JSONObject qitan = channelEntity.getJSONObject("qitan");
            data.setChannelQitanId(qitan.getLong("entity_id"));
            data.setChannelQiTanShow(qitan.containsKey("should_display") && qitan.getBoolean("should_display"));
            data.setEnable(channelEntity.containsKey("is_enable") && channelEntity.getBoolean("is_enable"));

            JSONArray platforms = channelEntity.getJSONArray("access_play_control");
            if (platforms != null) {
                Iterator<Object> t = platforms.iterator();
                JSONObject entity = null;
                while (t.hasNext()) {
                    entity = (JSONObject) t.next();
                    if (entity.getJSONObject("default_control") != null) {
                        if ("ONLINE".equalsIgnoreCase(entity.getJSONObject("default_control").getString("availabe_status"))) {
                            data.addOnlinePlatform(entity.getString("play_platform"));
                        }
                    }
                }
            } else {
                data.setPlatformEmpty(true);
            }

            JSONArray kvPair = channelEntity.getJSONArray("key_value_pair");
            if (kvPair != null) {
                Iterator<Object> t = kvPair.iterator();
                JSONObject entity = null;
                while (t.hasNext()) {
                    entity = (JSONObject) t.next();
                    if ("imageformat_livechannel_logo".equals(entity.getString("name"))) {
                        data.setDefaultLogoUrl(entity.getString("value"));
                    }
                }
            }

            data.setSubjectUrl(channelEntity.getString("subject_url"));

            JSONObject cqisuObj = channelEntity.getJSONObject("qisu");
            data.setCqisuUrl(cqisuObj.getString("url"));

            if (programEntity.containsKey("tag")) {
                data.setProgramTag(programEntity.getJSONArray("tag").toJSONString().replaceAll("\\[|\\]", ""));
            }
            JSONArray programPlatforms = programEntity.getJSONArray("access_play_control");
            if (programPlatforms != null) {
                Iterator<Object> t = programPlatforms.iterator();
                JSONObject entity = null;
                while (t.hasNext()) {
                    entity = (JSONObject) t.next();
                    if (entity.getJSONObject("default_control") != null) {
                        if ("ONLINE".equalsIgnoreCase(entity.getJSONObject("default_control").getString("availabe_status"))) {
                            data.addProgramOnlinePlatform(entity.getString("play_platform"));
                        }
                    }
                }
            } else {
                data.setProgramPlatformEmpty(true);
            }
            data.setProgramQipuId(programEntity.getLong("id"));
            JSONObject programMetaData = programEntity.getJSONObject("metadata");
            logger.info("programMetaData:"+programMetaData);
            data.setStartTime(DateTimeUtil.transLongFormat(programMetaData.getLong("start_play_time")));
            data.setEndTime(DateTimeUtil.transLongFormat(programMetaData.getLong("stop_play_time")));
            data.setProgramName(programMetaData.getString("program_name"));

            JSONObject programBase = programEntity.getJSONObject("base");
            data.setProgramAllowPopUps(programBase.containsKey("allow_popups") && programBase.getBoolean("allow_popups"));
            data.setPageUrl(programBase.getString("page_url"));
            data.setProgramBoss(programEntity.getJSONObject("boss").getString("status"));

            JSONArray programKvPair = programEntity.getJSONArray("key_value_pair");
            if (programKvPair != null) {
                Iterator<Object> t = programKvPair.iterator();
                JSONObject entity = null;
                while (t.hasNext()) {
                    entity = (JSONObject) t.next();
                    if ("imageformat_liveepisode_logo".equals(entity.getString("name"))) {
                        data.setProgramDefaultLogoUrl(entity.getString("value"));
                    }
                }
            }

            //追加节目 聊天室，道具，
            JSONObject propNode = programEntity.getJSONObject("prop");
            if (propNode != null) {
                data.setDaojuId(propNode.getString("channel_code"));
                data.setDaojuEnable(propNode.getBooleanValue("is_enabled"));
            }
            JSONObject qiTanNode = programEntity.getJSONObject("qitan");
            if (qiTanNode != null) {
                data.setProgramQitanId(qiTanNode.getLongValue("entity_id"));
                data.setProgramQiTanShow(qiTanNode.getBooleanValue("should_display"));
            }
            JSONObject chatRoomNode = programEntity.getJSONObject("chat_room_summary");
            if (chatRoomNode != null) {
                data.setChatRoomId(chatRoomNode.getLongValue("chat_room_id"));
                data.setChatDisplay(chatRoomNode.getBooleanValue("should_display"));
                data.setChatEnable(chatRoomNode.getBooleanValue("is_enable"));
            }
            // qisu url
            JSONObject pqisuObj = programEntity.getJSONObject("qisu");
            if (pqisuObj != null) {
                data.setPqisuUrl(pqisuObj.getString("url"));
            }
        } catch (Exception e) {
            logger.error("[CheckListTrigger][fetchQipuData] qipu base error", e);
            data.setHasError(true);
            data.setCheckErrorMsg("[decode qipu_base error]");
            return data;
        }
        try {
            fetchVRSData(data);
            return data;
        } catch (Exception e) {
            logger.error("[CheckListTrigger][fetchQipuData] qipu vrs error", e);
            data.setHasError(true);
            data.setCheckErrorMsg("[decode qipu_vrs error]");
            return data;
        }
    }

    private static void fetchVRSData(ProgramCheckListData data) {
        JSONObject json = null;
        if (ProgramData.FREE.equals(data.getProgramBoss())) {
            String buildUrl = ApiVrsRequestUtil.getVrsUrl(data.getChannelQipuId(), data.getProgramQipuId(), ApiVrsRequestUtil.S_SRC_15);
            json = ApiVrsRequestUtil.doQuery(buildUrl);
            if (json == null || !"A00000".equals(json.getString("code"))) {
                data.setVrsFirstResult(json == null ? "无法访问" : "访问异常：" + VRS_CODE_RESULT.get(json.getString("code")));
                data.setVrsFirstUrl(buildUrl);
                buildUrl = ApiVrsRequestUtil.getVrsUrl(data.getChannelQipuId(), data.getProgramQipuId(), ApiVrsRequestUtil.S_SRC_13);
                json = ApiVrsRequestUtil.doQuery(buildUrl);
            }
            data.setVrsNormalUrl(buildUrl);
        } else {
            Map<String, String> params = new HashMap<String, String>();
            params.put("lc", data.getChannelQipuId() + "");
            params.put("lp", data.getProgramQipuId() + "");
            String vrsUrl = ApiHttpRequestUtil.doGet(VRS_VIP_URL, null, params);
            vrsUrl = vrsUrl.substring(0, vrsUrl.lastIndexOf("&") - 1);
            data.setVrsVipUrl(vrsUrl);
            json = ApiHttpRequestUtil.getMethod(vrsUrl, null);
        }
        if (json == null) {
            data.setVrsVisitResult("无法访问");
            data.setVrsVisitRed(true);
            return;
        } else if ("A00000".equals(json.getString("code"))) {
            data.setVrsVisitResult("正常访问");
        } else {
            data.setVrsVisitResult("访问异常：" + VRS_CODE_RESULT.get(json.getString("code")));
            data.setVrsVisitRed(true);
            return;
        }
        JSONObject dataNode = json.getJSONObject("data");
        if (dataNode == null) {
            return;
        }

        JSONArray streamsArray = dataNode.getJSONArray("streams");
        Iterator<Object> t = streamsArray.iterator();
        JSONObject entity = null;
        Map<String, LinkData> map = new HashMap<String, LinkData>();
        String dealFormatType = null;
        while (t.hasNext()) {
            entity = (JSONObject) t.next();
            LinkData linkData = new LinkData();
            linkData.setLinkFormat(false);
            dealFormatType = dealWithDolbyType(entity.getString("formatType"));
            linkData.setUniqueKey(entity.getString("steamType") + "_" + dealFormatType);
            linkData.setStreamFormatType(dealFormatType);
            linkData.setSpanChKey(entity.getString("streamName"));
            linkData.setShowUrl(entity.getString("url"));
            doQuerySpans(linkData);
            map.put(linkData.getUniqueKey(), linkData);
        }

        data.setStreamMap(map);
    }

    private static String dealWithDolbyType(String formatType) {
        if (formatType != null && formatType.startsWith("DOLBY")) {
            return "DOLBY";
        }
        return formatType;

    }

    // version 版本统一2.0
    private static void doQuerySpans(LinkData linkData) {
        String url = QUERY_SPAN_URL;
        Map<String, String> params = new HashMap<String, String>();
        params.put("user", "ppslive");
        params.put("src_type", "PPC");
        params.put("version", "2.0");
        params.put("ch", linkData.getSpanChKey());
        if (linkData.isTs()) {
            url += "statm3u8_ts";
        } else if (linkData.isFLv()) {
            url += "statchannel";
        } else if (linkData.isDolby()) {
            url += "stathttp2ts";
        } else {
            logger.info("[queryStreamSpan] skip ;formatType={}", linkData.getStreamFormatType());
            return;
        }

        String resultValue = ApiHttpRequestUtil.doGet(url, null, params);
        if (resultValue != null) {
            try {
                JSONObject streamJSON = JSONObject.parseObject(resultValue);
                if (streamJSON != null) {
                    if (streamJSON.getIntValue("status") == 1) {
                        JSONObject jsonData = streamJSON.getJSONObject("data");
                        int span = jsonData.getIntValue("span");
                        linkData.setSpan(span);
                        if (span > 60) {
                            linkData.setSpanWarn(true);
                        }
                    }
                }
            } catch (Exception e) {
                logger.error("[CheckListTrigger] queryStreamSpan  Exception", e);
                return;
            }
        }
        logger.info("[queryStreamSpan] emtpy SpanChKey={}", linkData.getSpanChKey());
    }

    public Map<String, String> errorCheck(ProgramCheckListData qipuData, ProgramCheckListData localData) {
        Map<String, String> map = new HashMap<String, String>();

        boolean hasError = false;
        if (!qipuData.isEnable()) {
            hasError = true;
            map.put("{enable}", "未启");
        }
        if (qipuData.hasSpanWarn()) {
            hasError = true;
            map.put("{spans}", "span大于60");
        }
        if (qipuData.isPlatformEmpty()) {
            hasError = true;
            map.put("{c_ctrl_empty}", "频播无");
        } else if (qipuData.getOnlinePlatforms().isEmpty()) {
            hasError = true;
            map.put("{c_ctrl_off}", "频播全下");
        }
        if (qipuData.isProgramPlatformEmpty()) {
            hasError = true;
            map.put("{p_ctrl_empty}", "节播无");
        } else if (qipuData.getProgramOnlinePlatforms().isEmpty()) {
            hasError = true;
            map.put("{p_ctrl_off}", "节播全下");
        }
        //频道图片
        if (StringUtils.isBlank(qipuData.getDefaultLogoUrl())) {
            hasError = true;
            map.put("{c_pic_empty}", "频图无");
        }
        //节目图片
        if (StringUtils.isBlank(qipuData.getProgramDefaultLogoUrl())) {
            hasError = true;
            map.put("{p_pic_empty}", "节图无");
        }

        // 流编码
        if (localData.hasEncodeRed()) {
            hasError = true;
            map.put("{stream_encode}", "未编码");
        }
        if (localData.getStreamLogWarn() != -1) {
            hasError = true;
            String logInfo = "";
            if (localData.getStreamLogWarn() == Constants.LogType.ENCODE_START.getIndex()) {
                logInfo = "流延迟 [" + localData.getMaxLogTime() + "]";
            } else if (localData.getStreamLogWarn() == Constants.LogType.ENCODE_STOP.getIndex()) {
                logInfo = "流中断 [" + localData.getMaxLogTime() + "]";
            }
            map.put("{stream_log_type}", logInfo);
        }
        if (localData.getStreamAspectRatioWarn()) {
            map.put("{stream_aspect_ratio}", " 流分辨率 4:3 ");
        }
        if (hasError) {
            map.put("error", "true");
        }
        return map;
    }

    private String getTOList() {
        List<ChannelConfig> configs = channelService.getConfig("PMsgType");
        StringBuffer sb = new StringBuffer();
        int size = configs.size();
        for (int i = 0; i < size; i++) {
            if (i > 0) {
                sb.append(",");
            }
            sb.append(configs.get(i).getVal());
        }

        return sb.toString();
    }

    public void notifyDecodeError(ProgramCheckListData qipuData, ProgramCheckListData localData) {
        StringBuffer content = new StringBuffer(localData.getStartTime().substring(11) + "[" + localData.getEpisodeGrade() + "]" + "《" + localData.getProgramName() + "》" + localData.getProgramQipuId() + "\n");
        if (qipuData.isHasError()) {
            content.append(qipuData.getCheckErrorMsg());
        }
        if (localData.isHasError()) {
            content.append(localData.getCheckErrorMsg());
        }
        String sb = getTOList();
        if (sb.length() == 0) {
            logger.warn("[sendMsg] no phone number;msg=" + content.toString());
        }
        SendMsgUtils.sendMsg(sb, content.toString(), "【epg】", "warn");
    }

    public void checkSendMsg(ProgramCheckListData qipuData, ProgramCheckListData localData) {
        Map<String, String> map = errorCheck(qipuData, localData);
        if (map.containsKey("error")) {

            StringBuffer content = new StringBuffer(localData.getStartTime().substring(11) + "[" + localData.getEpisodeGrade() + "]" + "《" + localData.getProgramName() + "》" + localData.getProgramQipuId() + "\n");
            content.append("异常:");
            map.remove("error");
            StringBuffer errorBind = new StringBuffer();
            for (String errorMsg : map.values()) {
                errorBind.append(errorMsg + ",");
            }
            if (errorBind.length() > 0) {
                errorBind.deleteCharAt(errorBind.length() - 1);
            }
            content.append(errorBind);
            String sb = getTOList();
            if (sb.length() == 0) {
                logger.warn("[sendMsg] no phone number;msg=" + content.toString());
            }
            SendMsgUtils.sendMsg(sb, content.toString(), "【epg】", "warn");
        }
    }

    public static Map<String, Integer> transferServerList(List<RtmpServer> serverList) {
        Map<String, Integer> serverListMap = new HashMap<>();
        for (RtmpServer server : serverList) {
            serverListMap.put(server.getPublicIp(), server.getPort());
            serverListMap.put(server.getPrivateIp(), server.getPort());
        }

        return serverListMap;
    }

    public static Map<String, String> makeServerListMap(List<RtmpServer> serverList) {
        Map<String, String> serverListMap = new HashMap<>();
        for (RtmpServer server : serverList) {
            serverListMap.put(server.getPublicIp(), server.getPrivateIp());
            serverListMap.put(server.getPrivateIp(), server.getPublicIp());
        }

        return serverListMap;
    }

}

class TagJSON {
    private long id;
    private String name;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}